home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-03 | 15.1 KB | 581 lines | [TEXT/MPS ] |
- //----------------------------------------------------------------------------------------
- // UClassDesc.cp
- // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
- //----------------------------------------------------------------------------------------
-
- #ifndef __UCLASSDESC__
- #include "UClassDesc.h"
- #endif
-
- // MacApp
-
- #ifndef __UCLASSDESCITERATOR__
- #include "UClassDescIterator.h"
- #endif
-
- #ifndef __UDEBUG__
- #include "UDebug.h"
- #endif
-
- #ifndef __UCOREERRORMGR__
- #include "UCoreErrorMgr.h"
- #endif
-
- #ifndef __UFAILURE__
- #include "UFailure.h"
- #endif
-
- #ifndef __ULIST__
- #include "UList.h"
- #endif
-
- #ifndef __UTHEDEBUGGER__
- #include "UTheDebugger.h"
- #endif
-
- // Toolbox
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- // ANSI
-
- #ifndef __STRING__
- #include <string.h>
- #endif
-
- #if qDebugMsg
- #ifndef __STDIO__
- #include <stdio.h>
- #endif
- #endif
-
-
- //========================================================================================
- // GLOBALS
- //========================================================================================
-
- #if qDebug
- static void ClassDescInheritanceCheck();
- #endif
-
- //========================================================================================
- // CLASS ClassDesc
- //========================================================================================
- #pragma segment ClassDescRes
-
- //----------------------------------------------------------------------------------------
- // Static Data Members:
- //----------------------------------------------------------------------------------------
-
- // "Variables with storage class static that are not initialized are guaranteed to start
- // off as 0 converted to the appropriated type." ARM §8.4.
- //
- // Don't initialize the following static variable. It will be NULL at startup as described
- // above. When a global ClassDesc object is constructed it is added to this linked list.
- // C++ doesn't guarentee initialization order so if we initialize this to NULL and one
- // of the global ClassDesc objects has already been constructed and added itself to this
- // list, we will clobber the list if we initialize fgClassDescList to NULL.
-
- TClassDescListByName* ClassDesc::fgClassDescListByName;
- TClassDescListByID* ClassDesc::fgClassDescListByID;
- ClassDesc* ClassDesc::fgClassDescList;
- TClassDescSignatureList* ClassDesc::fgSignatures;
- ClassID ClassDesc::fgNextClassID;
-
- //----------------------------------------------------------------------------------------
- // Static Member Functions:
- //----------------------------------------------------------------------------------------
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::GetClassDescFromClassID:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
- MA_ClassReference ClassDesc::GetClassDescFromClassID(ClassID classID)
- {
- return fgClassDescListByID->FindByID(classID);
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::GetClassDescFromClassName:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
- MA_ClassReference ClassDesc::GetClassDescFromClassName(const ClassName& className)
- {
- return fgClassDescListByName->FindByName(className);
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::GetClassDescFromSignature:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
- MA_ClassReference ClassDesc::GetClassDescFromSignature(IDType signature)
- {
- return fgSignatures->FindBySignature(signature);
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::IsValidClassID:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- Boolean ClassDesc::IsValidClassID(ClassID classID)
- {
- // between 1 and number of classes
- return 1 <= classID && classID <= fgNextClassID;
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::NewByClassID:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- void* ClassDesc::NewByClassID(ClassID classID)
- {
- void* returnVal = NULL;
-
- MA_ClassReference classDesc = ClassDesc::GetClassDescFromClassID(classID);
-
- if (classDesc)
- returnVal = classDesc->Call_DefaultConstructor();
- else
- {
- #if qDebug
- ProgramBreak("The application doesn't contain the class with class ID " + CStr255(classID) + ".");
- #endif
-
- gErrorParm3 = CStr255(classID); // show ID of the class
- Failure(errMissingClass, 0);
- }
-
- return returnVal;
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::NewByClassName:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- void* ClassDesc::NewByClassName(const ClassName& className)
- {
- void* returnVal = NULL;
-
- MA_ClassReference classDesc = ClassDesc::GetClassDescFromClassName(className);
-
- if (classDesc)
- returnVal = classDesc->Call_DefaultConstructor();
- else
- {
- #if qDebug
- ProgramBreak("The application doesn't contain the class " + className + ".");
- #endif
-
- gErrorParm3 = className; // show name of the class
- Failure(errMissingClass, 0);
- }
-
- return returnVal;
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::NewBySignature:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- void* ClassDesc::NewBySignature(IDType signature)
- {
- void* returnVal = NULL;
-
- MA_ClassReference classDesc = ClassDesc::GetClassDescFromSignature(signature);
-
- if (classDesc)
- returnVal = classDesc->Call_DefaultConstructor();
- else
- {
- #if qDebugMsg
- fprintf(stderr, "signature='%4s'\n", (char*) & signature);
- ProgramBreak("Unable to find class for the given signature");
- #endif
-
- Failure(errMissingSignature, 0);
- }
-
- return returnVal;
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::InitUClassDesc:
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- void ClassDesc::InitUClassDesc()
- {
- // Build the sorted class lists. These have to be built sometime after InitUMemory.
- // It would be nice to be able to do this at static initialization time.
-
- MAVolatileInit(TClassDescListByName * , byName, NULL);
- MAVolatileInit(TClassDescListByID * , byID, NULL);
- MAVolatileInit(TClassDescSignatureList * , signatures, NULL);
-
- FailInfo fi;
- Try(fi)
- {
- // build sorted lists of ClassDesc from linked list
- ArrayIndex numberOfClasses = fgNextClassID;
-
- #if qTheDebugger
- TheDbgr_Adjust_ClassDescr_Ids(fgClassDescList, numberOfClasses);// re-order the Class ID's
- #endif
-
- byName = new TClassDescListByName;
- byName->IClassDescListByName(numberOfClasses);
-
- byID = new TClassDescListByID;
- byID->IClassDescListByID(numberOfClasses);
-
- CClassIterator iter;
- MA_ClassReference classDesc;
-
- for (classDesc = iter.FirstClassDesc(); iter.More(); classDesc = iter.NextClassDesc())
- {
- // UNORDERED - Insert the ClassDesc into the lists by name and by ID.
- byName->InsertElementsBefore(byName->GetSize() + 1, &classDesc, 1);
- byID->InsertElementsBefore(byID->GetSize() + 1, &classDesc, 1);
- }
-
- // Now ORDER the lists
- byName->Sort();
- byID->Sort();
-
- // set these now, we need them in the rest
- fgClassDescListByName = byName;
- fgClassDescListByID = byID;
-
- #if qTheDebugger
- gExtDbgr_Info.n_classes = byID->GetSize();
-
- gExtDbgr_Info.pOrderedClass = (T_ClassList * *) & byID->fArraySpace;// pointer to pointer to array of ClassDesc
- gExtDbgr_Info.MA_ClassTblPtr = (T_ClassList * *) & byName->fArraySpace;// pointer to pointer to array of ClassDesc
- #endif
-
- #if qDebug
- ClassDescInheritanceCheck();
- #endif
-
- signatures = new TClassDescSignatureList;
- signatures->IClassDescSignatureList(0);
- fgSignatures = signatures;
-
- fi.Success();
- }
- else // Recover
- {
- if (byName)
- {
- byName->DeleteAll();
- byName->Free();
- }
-
- if (byID)
- {
- byID->DeleteAll();
- byID->Free();
- }
-
- if (signatures)
- {
- signatures->DeleteAll();
- signatures->Free();
- }
-
- fi.ReSignal();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::ClassDesc:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- ClassDesc::ClassDesc(const char* className,
- size_t classSize,
- MA_ClassReference const* ancestors,
- const ptrdiff_t* const offsets) :
- fClassName(className),
- fClassSize(classSize),
- fAncestors(ancestors),
- fAncestorOffsets(offsets)
- {
- // #if qDebug
- // // Check for duplicate class descriptor
- // CClassIterator iter;
- // MA_ClassReference classDesc;
- // for (classDesc = iter.FirstClassDesc(); iter.More(); classDesc = iter.NextClassDesc())
- // {
- // if (classDesc == this)
- // {
- // ClassName name = this->GetClassName();
- // ProgramBreak("Duplicate class descriptor for " + name + "!");
- // }
- // }
- // #endif
-
- // link list of ClassDesc
- fNextClassDesc = fgClassDescList;
- fgClassDescList = this;
-
- // AssignNewClassID
- fClassID =++fgNextClassID;
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::Call_DefaultConstructor:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- void* ClassDesc::Call_DefaultConstructor() const
- {
- void* returnVal = NULL;
-
- if (fDefaultConstructor)
- returnVal = (*(ConstructorProcPtr)fDefaultConstructor)();
- else
- {
- gErrorParm3 = GetClassName(); // show name of the class
- #if qDebug
- ProgramBreak("Class " + gErrorParm3 + " does not appear to have been registered.");
- #endif
-
- Failure(errMissingClass, 0);
- }
-
- return returnVal;
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::CountBaseClasses:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- ArrayIndex ClassDesc::CountBaseClasses() const
- {
- ArrayIndex count = 0;
- MA_ClassReference
- const* ancestors = fAncestors;
-
- while (*ancestors != 0)
- {
- count++;
- ancestors++;
- }
-
- return count;
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::DynamicCast:
- //----------------------------------------------------------------------------------------
-
- void* ClassDesc::DynamicCast(const void* p,
- MA_ClassReference pointersClass,
- MA_ClassReference aBaseClass) const
- {
- ptrdiff_t offset;
- char* q = 0;
-
- if (pointersClass == aBaseClass)
- {
- if (this->DescendsFrom(aBaseClass))
- q = (char*)p;
- }
- else if (this->OffsetToBase(pointersClass, offset))
- {
- q = ((char*)p) - offset;
- if (this->OffsetToBase(aBaseClass, offset))
- q += offset;
- else
- q = 0;
- }
-
- #if qDebugMsg
- if (!q)
- {
- if (gIntenseDebugging)
- fprintf(stderr, "Cannot dynamic cast a %s from %s to %s\n", GetClassName(), pointersClass->GetClassName(), aBaseClass->GetClassName());
- }
- #endif // qDebugMsg
-
- return q;
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::GetBaseClass:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- MA_ClassReference ClassDesc::GetBaseClass(ArrayIndex index) const
- {
- #if qRangeCheck
- if (index > CountBaseClasses())
- {
- #if qDebug
- ProgramBreak("Base class index out of range!");
- #endif
-
- Failure(minErr, 0);
- }
- #endif
-
- return fAncestors[index - 1];
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::DescendsFrom:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- IDType ClassDesc::GetSignature() const
- {
- return fgSignatures->FindByClassDesc(this);
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::DescendsFrom:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- Boolean ClassDesc::DescendsFrom(MA_ClassReference classDesc,
- Boolean directDescendant) const
- {
- Boolean result = FALSE;
-
- // Is it this class?
-
- if (classDesc == this)
- result = TRUE;
- else
- {
- MA_ClassReference
- const* ancestors = fAncestors;
-
- // Is it a direct ancestor?
-
- while (*ancestors != 0)
- {
- if (*ancestors == classDesc)
- {
- result = TRUE;
- break;
- }
- ancestors++;
- }
-
- // Recursively check our more remote ancestors.
-
- if ((!result) && (!directDescendant))
- {
- ancestors = fAncestors;
-
- while (*ancestors != 0)
- {
- if ((*ancestors)->DescendsFrom(classDesc))
- {
- result = TRUE;
- break;
- }
- ancestors++;
- }
- }
- }
-
- return result;
- }
-
- // ClassDesc::OffsetToBase:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- void ClassDesc::RegisterSignature(IDType signature)
- {
- fgSignatures->RegisterSignature(this, signature);
- }
-
- //----------------------------------------------------------------------------------------
- // ClassDesc::OffsetToBase:
- //----------------------------------------------------------------------------------------
- #pragma segment ClassDescRes
-
- Boolean ClassDesc::OffsetToBase(MA_ClassReference aBaseClass,
- ptrdiff_t& offset) const
- {
- Boolean result = FALSE;
-
- if (aBaseClass == this)
- {
- offset = 0;
- result = TRUE;
- }
- else
- {
- MA_ClassReference
- const* ancestors = fAncestors;
-
- while (*ancestors != 0)
- {
- if ((*ancestors)->OffsetToBase(aBaseClass, offset))
- {
- offset += fAncestorOffsets[ancestors - fAncestors];
- result = TRUE;
- break;
- }
- ancestors++;
- }
- }
-
- return result;
- }
-
- //========================================================================================
- // GLOBAL Functions
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // ClassDescInheritanceCheck:
- //----------------------------------------------------------------------------------------
- #pragma segment MAInit
-
- #if qDebug
-
- void ClassDescInheritanceCheck()
- {
- CClassIterator iter;
- MA_ClassReference classDesc;
-
- for (classDesc = iter.FirstClassDesc(); iter.More(); classDesc = iter.NextClassDesc())
- {
- ArrayIndex n = classDesc->CountBaseClasses();
- ArrayIndex i;
- for (i = 1; i <= n; i++)
- {
- MA_ClassReference baseClassDesc = classDesc->GetBaseClass(i);
- if (baseClassDesc->DescendsFrom(classDesc))
- {
- #if qDebugMsg
- fprintf(stderr, "Class %s descends from itself through %s\n", classDesc->GetClassName(), baseClassDesc->GetClassName());
- #endif // qDebugMsg
-
- ProgramBreak("Inheritance loop!");
- Failure(minErr, 0);
- }
- }
- }
- }
-
- #endif // qDebug
-
- //----------------------------------------------------------------------------------------
- // End of UClassDesc.cp
-
- #pragma segment Inline
-